#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "analisador.h"

int isListaStringVazia(ListaString L) {
	return (L.Primeiro->prox == NULL);
}

void criarListaString(ListaString *L) {
	L->Primeiro = (PItemString)malloc(sizeof(ItemString));
	L->Ultimo = (PItemString)malloc(sizeof(ItemString));
	L->Primeiro->prox = NULL;
	L->Ultimo->prox = NULL;
}

void inserirItemString(ListaString *L, char *texto) {
	PItemString P = (PItemString)malloc(sizeof(ItemString));
	P->texto = texto;

	if(isListaStringVazia(*L))
		L->Primeiro->prox = P;
	else
	{
		L->Ultimo->prox->prox = P;
	}
	L->Ultimo->prox = P;
	P->prox = NULL;
}

void imprimirListaString(ListaString L) {
	PItemString aux = L.Primeiro->prox;
	while (aux != NULL)
	{
		printf("\n%s", aux->texto);
		aux = aux->prox;
	}
}

/*
 *
 */
void decrementarPosicao(ListaChunk *L, int posicaoPilhaInicio) {

	PChunk aux = L->Primeiro->prox;
	while (aux != NULL)
	{
		if(aux->itemChunk.auxValor >= posicaoPilhaInicio) {
			aux->itemChunk.auxValor = aux->itemChunk.auxValor - 1;
		}
		aux = aux->prox;
	}
}

/**
 *
 */
PChunk get(ListaChunk L, long idVideo, long indiceChunk) {

	PChunk aux = L.Primeiro->prox;
	while (aux != NULL)
	{
		if(aux->itemChunk.idVideo == idVideo && aux->itemChunk.indiceChunk == indiceChunk) {
			return aux;
		}
		aux = aux->prox;
	}
	return (NULL);
}


/**
 * Verifica se a lista de chunks está vazia
 * L -> estrutura ListaChunk
 */
int isListaChunkVazia(ListaChunk L) {
	return (L.Primeiro->prox == NULL);
}

/**
 * Aloca uma lista encadeada de chunks
 * L -> estrutura ListaChunk
 */
void criarListaChunk(ListaChunk *L) {
	L->Primeiro = (PChunk)malloc(sizeof(Chunk));
	L->Ultimo = (PChunk)malloc(sizeof(Chunk));
	L->Primeiro->prox = NULL;
	L->Ultimo->prox = NULL;
	L->size = 0;
}

/**
 * Insere a referência para um item na lista encadeada
 * L -> lista encadeada
 * P -> ponteiro para o item a ser inserido
 */
void inserirPonteiroChunk(ListaChunk *L, PChunk P) {
	if(isListaChunkVazia(*L))
		L->Primeiro->prox = P;
	else
	{
		L->Ultimo->prox->prox = P;
	}
	L->Ultimo->prox = P;
	P->prox = NULL;
	L->size = L->size + 1;
}

/**
 * Insere um chunk
 * na lista encadeada de Chunks
 */
void inserirChunk(ListaChunk *L, long idVideo, long indiceChunk, long tamanhoChunk, int posicaoPilha) {

	PChunk P = (PChunk)malloc(sizeof(Chunk));
	ItemChunk item;
	item.idVideo = idVideo;
	item.indiceChunk = indiceChunk;
	item.tamanhoChunk = tamanhoChunk;
	item.auxValor = posicaoPilha;

	P->itemChunk = item;

	inserirPonteiroChunk(L,P);
}

/**
 * Imprime os dados da lista encadeada de chunks
 */
void imprimirListaChunk(ListaChunk L) {

	PChunk aux = L.Primeiro->prox;
	while (aux != NULL)
	{
		printf("\nId Video: %ld, Indice chunk: %ld Tamanho: %ld, p: %d ", aux->itemChunk.idVideo, aux->itemChunk.indiceChunk, aux->itemChunk.tamanhoChunk, aux->itemChunk.auxValor);
		aux = aux->prox;
	}
}

/**
 * Libera a memória alocada pela lista encadeada de chunks
 */
ListaChunk *liberaListaChunk(ListaChunk L) {
	PChunk p = L.Primeiro->prox;
	while (p != NULL) {
		PChunk t = p->prox;
		free(p);
		p = t;
	}
	return (NULL);
}

ItemChunk *insertionSort(ListaChunk L, int tam) {

	ItemChunk *vetor = (ItemChunk*)malloc(tam*sizeof(ItemChunk));

	int indiceVetor = 0;
	PChunk aux = L.Primeiro->prox;
	while (aux != NULL)
	{
		vetor[indiceVetor] = aux->itemChunk;
		aux = aux->prox;
		indiceVetor++;
	}

	int i, j;
	ItemChunk chave;
	i = 0;

	for (j=1;j<tam;j++)
	{
	  chave = vetor[j];
	  i = j - 1;

	  while((i >=0) && (vetor[i].idVideo > chave.idVideo || (vetor[i].idVideo == chave.idVideo && vetor[i].indiceChunk > chave.indiceChunk) ) ) {

		  vetor[i+1] = vetor[i];
		  i--;
	  }

	  vetor[i+1] = chave;
	}

	return vetor;

}
